home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 2: Applications
/
Linux Cubed Series 2 - Applications.iso
/
circuits
/
irsim-ca.2
/
irsim-ca
/
irsim-cap-9.2
/
src
/
ana11
/
postscript.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-29
|
17KB
|
654 lines
/*
* *********************************************************************
* * Copyright (C) 1988, 1990 Stanford University. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. Stanford University *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
*/
#include <pwd.h>
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include "ana.h"
#include "ana_glob.h"
#define DATE_LEN 25 /* length of ascii date returned by ctime */
private int psBanner = TRUE;
private int psLegend = FALSE;
private int psTimes = TRUE;
private int psOutline = TRUE;
private void WritePSfile(), DrawOutline(), PrintNames(), PrintTraces();
private void PrintSignal(), PrintVector(), PrintTimes(), PrintLegend();
public void SetPSParms( s )
char *s;
{
int *parm;
switch( s[1] )
{
case 'b' :
psBanner ^= TRUE;
break;
case 'l' :
psLegend ^= TRUE;
break;
case 't' :
psTimes ^= TRUE;
break;
case 'o' :
psOutline ^= TRUE;
break;
}
if( *s == MENU_UNMARK )
*s = MENU_MARK;
else
*s = MENU_UNMARK;
}
typedef enum { black, white, gray, xpat } pattern;
private char fname[256] = "";
private FILE *psout;
private pattern currPat;
public void printPS( s )
char *s;
{
if( traces.disp == 0 or tims.first >= tims.last )
{
PRINT( "\nThere's nothing to print" );
XBell( display, 0 );
return;
}
if( *fname == '\0' )
{
(void) strncpy( fname, banner, bannerLen );
fname[bannerLen] = '\0';
(void) strcat( fname, ".ps" );
}
PRINTF( "\nEnter filename (%s)", fname );
Query( " > ", WritePSfile );
}
private void WritePSfile( psfname )
char *psfname;
{
/* struct passwd *pass ;
char *UserName;
char *tmp;
int UserNameLength;
*/
char *date;
time_t theTime, time();
if( psfname == NULL )
return;
if( *psfname == '\0' )
psfname = fname;
else
(void) strcpy( fname, psfname );
if( (psout = fopen( psfname, "w" )) == NULL )
{
PRINTF( "\ncan't open '%s' for output", psfname );
return;
}
PRINTF( "\nWriting %s...", psfname );
XDefineCursor( display, window, cursors.timer );
XFlush( display );
currPat = black;
WritePreamble();
theTime = time( 0 );
date = ctime( &theTime );
/* pass = getpwuid(getuid()) ;
UserName = tmp = pass->pw_name;
for (UserNameLength=0; *tmp != '\0'; tmp++ ) UserNameLength++ ;
printf(" date= %s, USER= %s, UserLength= %d \n",date,UserName ,UserNameLength );
*/
fprintf( psout, "MSAVE\n" );
DrawOutline( date );
if( psTimes )
PrintTimes( tims.start, tims.end );
PrintNames();
PrintTraces( tims.start, min( tims.end, tims.last ) );
fprintf( psout, "showpage MRESTORE\n" );
if( psLegend )
{
DrawOutline( date );
PrintLegend();
fprintf( psout, "showpage\n" );
}
(void) fclose( psout );
PRINT( "done" );
XDefineCursor( display, window, cursors.deflt );
}
/* Macros to Convert from screen to PostScript units */
#define PS_UNITS 72 /* PostScript unit (1/inch) */
#define ps_YSIZE (15 * PS_UNITS / 2) /* y page size = 7.5 inch */
#define ps_XSIZE (10 * PS_UNITS) /* x page size = 10 inch */
#define XMARGIN (PS_UNITS / 2) /* margins 1/2 inch */
#define YMARGIN (PS_UNITS / 2)
#define FSIZE 9 /* default font size */
#define MINFSIZE 4 /* minimum font size */
#define LEGFSIZE 7 /* legend font size */
#define YTRACE (traceBox.bot - traceBox.top + 1)
#define TIMES_HEIGHT 20
#define BANNER_HEIGHT 15
#define psHEIGHT ( ps_YSIZE - TIMES_HEIGHT - BANNER_HEIGHT )
/* scale conversion macros */
#define PSX( x ) ( (x) * (ps_XSIZE - 2) / traceBox.right )
#define PSY( y ) ( (YWINDOWSIZE - (y)) * psHEIGHT / YTRACE )
#define PS( x, y ) PSX( x ), PSY( y )
#define BANNER_BOT ( psHEIGHT + PSY( traceBox.bot ) )
#define BANNER_TOP ( BANNER_BOT + BANNER_HEIGHT )
#define BANNER_MID ( (BANNER_TOP + BANNER_BOT + 1) / 2 )
#define TIMES_TOP PSY( traceBox.bot )
#define TIMES_BOT (TIMES_TOP - TIMES_HEIGHT )
/**************************************************************************/
/* Redefine the graphics operators to generate the PostScript code */
/**************************************************************************/
#define BLACK 1 /* anything will do */
#define WHITE 0
#define VLine( X, BOT, TOP, COLOR ) \
fprintf( psout, "%d %d %d VL\n", PS( X, BOT), PSY( TOP ) );
#define HLine( LEFT, RIGHT, Y, COLOR ) \
fprintf( psout, "%d %d %d HL\n", PS( LEFT, Y ), PSX( RIGHT ) );
#define Line( X1, Y1, X2, Y2 ) \
fprintf( psout, "%d %d %d %d L\n", PS( X1, Y1 ), PS( X2, Y2 ) );
#define FillAREA( X, Y, WIDTH, HEIGHT, COLOR ) \
{ \
pattern opatt = SetPattern( COLOR ); \
fprintf( psout, "%d %d %d %d BOX fill\n", PS( X, Y ), \
PS( (X) + (WIDTH) - 1, (Y) + (HEIGHT) - 1 ) ); \
(void) SetPattern( opatt ); \
} \
#define StrLeft( S, LEN, LEFT, BOT, FG, BG ) \
{ \
psString( S, LEN ); \
fprintf( psout, "%d %d SL\n", PS( LEFT, BOT ) ); \
} \
#define StrRight( S, LEN, RIGHT, MID, FG, BG ) \
{ \
psString( S, LEN ); \
fprintf( psout, "%d %d SR\n", PS( RIGHT, MID ) ); \
} \
#define StrCenter( S, LEN, LEFT, RIGHT, MID, FG, BG ) \
{ \
psString( S, LEN ); \
fprintf( psout, "%d %d %d SC\n", PSX( LEFT ), PS( RIGHT, MID ) ); \
} \
/**************************************************************************/
/*
* Write out an string, prepending parens with '\'
*/
private void psString( s, len )
char *s;
int len;
{
putc( '(', psout );
while( *s != '\0' and len != 0 )
{
if( (*s == '(' ) || (*s == ')') )
putc( '\\', psout );
putc( *s, psout );
s++;
len--;
}
putc( ')', psout );
}
private pattern SetPattern( patt )
pattern patt;
{
float grayscale;
pattern ret;
if( patt == white )
grayscale = 1.0;
else if( patt == gray )
grayscale = 0.82;
else if( patt == xpat )
grayscale = 0.68;
else /* black */
grayscale = 0.0;
fprintf( psout, "%g setgray\n", grayscale );
ret = currPat;
currPat = patt;
return( ret );
}
private void DrawOutline( date )
char *date;
{
pattern opatt;
char info[ 256 ];
struct passwd *pass ;
char *UserName;
char *tmp;
int UserNameLength;
pass = getpwuid(getuid()) ;
UserName = tmp = pass->pw_name;
for (UserNameLength=0; *tmp != '\0'; tmp++ ) UserNameLength++ ;
if( psBanner )
{
opatt = SetPattern( gray );
fprintf( psout, "%d %d %d %d BOX fill \n", 0, BANNER_BOT, ps_XSIZE, BANNER_TOP);
(void) SetPattern( opatt );
fprintf (psout, "%d %d %d %d BOX stroke \n", 0, BANNER_BOT, ps_XSIZE, BANNER_TOP);
(void) sprintf( info, "USER:%s", UserName);
psString( info, UserNameLength + 5 );
fprintf( psout, "%d %d FSIZE 2 div sub SL\n", 6, BANNER_MID );
(void) sprintf( info, "FILE:%s", banner);
psString( info, bannerLen + 5 );
fprintf( psout, "%d %d FSIZE 2 div sub SL\n",
(int) PSX( traceBox.right - 4 ) / 2,
BANNER_MID );
if( strncmp( banner, fname, bannerLen ) != 0 )
{
(void) sprintf( info, "(%s) %s", fname, date );
psString( info, bannerLen + DATE_LEN );
}
else
psString( date, DATE_LEN );
fprintf( psout, " %d %d SR\n", PSX( traceBox.right - 4 ), BANNER_MID);
}
if( psOutline )
fprintf( psout, "%d %d %d %d BOX stroke \n", 0, TIMES_BOT, ps_XSIZE, BANNER_TOP);
}
/* FactorTbl: time grid at multiples of 1/FactorTbl => .1 .5 .25 1 */
private int FactorTbl[] = { 10, 2, 4, 1};
private void PrintTimes( t1, t2 )
TimeType t1, t2;
{
TimeType step, half_step, i;
int x;
char s[ 25 ];
for( step = tims.steps, i = 1; step >= 10; step /= 10, i *= 10 );
for( x = 0; ; x++ )
{
int nsteps = tims.steps /( i / FactorTbl[x] );
if( nsteps > 5 and nsteps < 15 )
break;
}
step = i / FactorTbl[x];
half_step = ( step > 2 ) ? (step / 2) - 1 : 2;
fprintf( psout, "0 setlinewidth [1 3] 0 setdash /svfnt currentfont def\n");
fprintf( psout, "theFont 0.7 FSIZE mul scalefont setfont\n" );
psString( "time (ns)", 30 );
fprintf( psout, " %d %d %d SC\n", 0, PSX(traceBox.left) - 1, TIMES_TOP );
i = ((t1 + step - 1) / step) * step;
if( i != t1 )
{
x = TimeToX( t1 );
VLine( x, traceBox.top, traceBox.bot + 3, BLACK );
if( i - t1 >= half_step )
{
(void) sprintf( s, "%.1f", d2ns( t1 ) );
x = 2 * PSX( x );
fprintf( psout, "(%s) 0 %d %d SC\n", s, x, (TIMES_BOT+TIMES_TOP)/2 );
}
}
while( i <= t2 )
{
x = TimeToX( i );
VLine( x, traceBox.top, traceBox.bot + 3, BLACK );
(void) sprintf( s, "%.1f", d2ns( i ) );
x = 2 * PSX( x );
fprintf( psout, "(%s) 0 %d %d SC\n", s, x, (TIMES_BOT+TIMES_TOP)/2 );
i += step;
}
if( i > t2 and (t2 - i + step) >= half_step )
{
x = TimeToX( t2 );
VLine( x, traceBox.top, traceBox.bot + 3, BLACK );
(void) sprintf( s, "%.1f", d2ns( t2 ) );
x = PSX( x );
fprintf( psout, "(%s) %d %d SR\n", s, x, (TIMES_BOT+TIMES_TOP)/2 );
}
HLine( traceBox.left - 2, traceBox.right, traceBox.bot, BLACK );
fprintf( psout, "0.6 setlinewidth [] 0 setdash svfnt setfont\n" );
}
private void PrintNames()
{
Coord x, y;
TraceEnt *t;
int i;
x = namesBox.right - 2;
for( t = traces.first, i = traces.disp; i != 0; i--, t = t->next )
{
y = (t->bot + t->top) / 2;
StrRight( t->name, t->len, x, y, BLACK, WHITE );
}
}
private void PrintTraces( t1, t2 )
TimeType t1,t2;
{
Trptr t;
int nt;
for( t = traces.first, nt = traces.disp; nt != 0; nt--, t = t->next )
{
if( IsVector( t ) )
PrintVector( t, t1, t2 );
else
PrintSignal( t, t1, t2 );
}
}
private void PrintSignal( t, t1, t2 )
Trptr t;
register TimeType t1, t2;
{
register hptr h;
register int val, change;
int x1, x2;
if( t1 >= tims.last )
return;
h = t->cache[0].wind;
x1 = TimeToX( t1 );
while( t1 < t2 )
{
val = h->val;
while( h->time < t2 and h->val == val )
NEXTH( h, h );
if( h->time > t2 )
{
change = FALSE;
t1 = t2;
}
else
{
change = ( h->val != val );
t1 = h->time;
}
x2 = TimeToX( t1 );
switch( val )
{
case LOW :
HLine( x1, x2, t->bot, WHITE );
break;
case HIGH :
HLine( x1, x2, t->top, WHITE );
break;
case X :
FillAREA( x1, t->top, x2 - x1 + 1, t->bot - t->top + 1, xpat );
if( x1 > traceBox.left + 1 )
VLine( x1, t->bot, t->top, WHITE );
break;
}
if( change )
VLine( x2, t->bot, t->top, WHITE );
x1 = x2;
}
}
private void PrintVector( t, t1, t2 )
register Trptr t;
register TimeType t1, t2;
{
hptr *start, *changes;
TimeType firstChange;
int x1, x2, xx, mid, nbits, strlen;
if( t1 >= tims.last )
return;
nbits = t->n.vec->nbits;
start = tmpHBuff;
changes = &(tmpHBuff[ nbits ]);
strlen = (nbits + t->bdigit - 1) / t->bdigit;
{
register hptr h, *s;
register int n, val;
register hptr *ch = changes;
register TimeType tm = tims.end;
s = start; /* initialize start array */
firstChange = tims.start;
for( n = nbits - 1; n >= 0; n-- )
{
h = s[n] = t->cache[n].wind;
val = h->val;
while( h->time < tm and h->val == val )
NEXTH( h, h );
ch[n] = h;
}
}
mid = (t->top + t->bot) / 2;
x2 = TimeToX( t2 );
x1 = TimeToX( firstChange );
while( t1 < t2 )
{
{ /* find nearest change in time */
register hptr *ch;
register int n;
t1 = tims.end + 1;
for( ch = changes, n = nbits - 1; n >= 0; n-- )
{
if( ch[n]->time < t1 )
t1 = ch[n]->time;
}
}
if( t1 <= t2 ) /* change before t2 => draw it */
{
x2 = TimeToX( t1 );
if( x2 - x1 > 3 )
{
HLine( x1 + 2, x2 - 2, t->top, WHITE );
HLine( x1 + 2, x2 - 2, t->bot, WHITE );
xx = 2;
}
else
xx = (x2 - x1 - 2);
VLine( x2, t->bot - 2, t->top + 2, WHITE );
if( x2 > traceBox.left + 1 )
{
Line( x2 - xx, t->top, x2, t->top + 2 );
Line( x2 - xx, t->bot, x2, t->bot - 2 );
}
if( x2 < traceBox.right - 1 )
{
Line( x2, t->top + 2, x2 + 2, t->top );
Line( x2, t->bot - 2, x2 + 2, t->bot );
}
}
else /* change after t2 */
{
register TimeType tm;
tm = min( t1, min( tims.end, tims.last ) );
x2 = TimeToX( tm );
HLine( x1 + 2, x2, t->top, WHITE );
HLine( x1 + 2, x2, t->bot, WHITE );
}
{
char *str;
str = HistToStr( start, nbits, t->bdigit, 1 );
StrCenter( str, strlen, x1, x2, mid, WHITE, BLACK );
}
{
register hptr h;
register hptr *ch, *s;
register int n, val;
register TimeType tm = tims.end;
for( s = start, ch = changes, n = nbits - 1; n >= 0; n-- )
{
if( ch[n]->time == t1 )
{
h = s[n] = ch[n];
val = h->val;
while( h->time < tm and h->val == val )
NEXTH( h, h );
ch[n] = h;
}
}
}
x1 = x2;
}
}
private void PrintLegend()
{
int i, nbits;
TraceEnt *t;
fprintf( psout, "/GX %d def\n", PSX( namesBox.right + 25 ) );
fprintf( psout, "/GY %d def\n", BANNER_BOT - 2 * (FSIZE + 3) );
fprintf( psout, "(Legend:) 4 %d SL\n", BANNER_BOT - FSIZE - 2 );
fprintf( psout, "/FSIZE %d def FSIZE SF\n", LEGFSIZE );
for( i = traces.disp, t = traces.first; i != 0; i--, t = t->next )
{
if( t->vector )
{
for( nbits = t->n.vec->nbits - 1; nbits >= 0; nbits-- )
psString( t->n.vec->nodes[nbits]->nname, 1000 );
nbits = t->n.vec->nbits;
}
else
{
psString( t->n.nd->nname, 1000 );
nbits = 1;
}
psString( t->name, 1000 );
fprintf( psout, "%d LE\n", nbits );
}
}
WritePreamble()
{
static char defs[] = "%!\n\
/MSAVE { /mStat save def } def\n\
/MRESTORE { mStat restore } def\n\
/SET { exch def } def\n\
/SF { /wi SET theFont [wi 0 0 FSIZE 0 0] makefont setfont } def\n\
/L { newpath moveto lineto stroke } def\n\
/VL { 2 index exch L } def\n\
/HL { 1 index L } def\n\
/BOX { /@yb SET /@xb SET /@yt SET /@xt SET newpath\n\
@xb @yb moveto @xb @yt lineto @xt @yt lineto @xt @yb lineto closepath } def\n\
/SL { moveto show } def\n\
/SR { exch dup /@xr SET 2 index stringwidth pop sub dup\n\
0 le { pop 0 @xr 3 -1 roll SC } { exch FSIZE 2 div sub moveto show }\n\
ifelse } def\n\
/SCP { /@s SET @s stringwidth pop /@sw SET @sw 2 div sub\n\
dup @sw add maxX gt { pop maxX @sw sub } if exch moveto @s show } def\n\
/SC { FSIZE 2 div sub /@y SET /@x2 SET /@x1 SET /@s SET\n\
/@l @x2 @x1 sub def /@x @x1 @x2 add 2 div def\n\
/@w @s stringwidth pop def @l @w gt\n\
{ @y @x @s SCP }\n\
{ @l FSIZE mul @w 1 add div dup MINFSIZE lt\n\
{ pop } { /svf currentfont def SF @y @x @s SCP svf setfont } ifelse }ifelse\n\
} def\n\
/LE { exch GX GY FSIZE 2 div add SR /@x GX def\n\
{ dup stringwidth pop /@w SET /@x @x FSIZE add def @x @w add\n\
720 ge { /@x GX FSIZE add def /GY GY FSIZE 2 add sub def } if\n\
@x GY SL /@x @x @w add def } repeat /GY GY FSIZE 4 add sub def } def\n\
";
/* print data and procedure definitions */
fprintf( psout, "%s", defs );
fprintf( psout, "/FSIZE %d def /MINFSIZE %d def ", FSIZE, MINFSIZE );
fprintf( psout, "/maxX %d def\n", PSX( traceBox.right ) );
/* Switch to landscape mode */
fprintf( psout, "%d 0 translate\n", 17 * PS_UNITS / 2 );
fprintf( psout, "90 rotate\n" );
fprintf( psout, "%d %d", XMARGIN, YMARGIN + TIMES_HEIGHT -
PSY( traceBox.bot) );
fprintf( psout, " translate\n" );
fprintf( psout, "1 setlinecap 0.6 setlinewidth \n" );
/* Set up text font */
fprintf( psout,"/theFont /Helvetica findfont def FSIZE SF\n");
}